package com.apobates.forum.toro.proxy.strategy;

import com.apobates.forum.toro.proxy.MapperMultiAttrExpression;
import com.apobates.forum.toro.proxy.MapperMultiAttrStatements;
import com.apobates.forum.toro.utils.BeanHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

public class MapperSerialManyStrategy<E> extends AbstractProxyStrategy<E> implements MapperManyStrategy<E>{
    private static final Logger logger = LoggerFactory.getLogger(MapperSerialManyStrategy.class);
    @Override
    public void consumer(Set<MapperMultiAttrExpression> selectExprSet, Collection<E> targetObjSet, Map<String, Set<String>> batchQueryArgs) {
        logger.debug("[MSMS][SerialMany]many parallel strategy start");
        // 获取数据源(key=设置目标的属性名, value候选的关联对象集合)
        final Map<String, Collection<Object>> rawSource = new HashMap<>();
        // key = selectAttr, value = Argument
        final Map<String, MapperMultiAttrStatements.Argument> selectAttrMap = new HashMap<>();
        // 4)构造后续操作的数据集
        for(MapperMultiAttrExpression mmas : selectExprSet){
            // 未找到关联参数集合
            if(!batchQueryArgs.containsKey(mmas.getTargetAttr())) {
                String tt = "[MSMS][SerialMany]target attr name no args, for:"+mmas.getTargetAttr();
                logger.debug(tt);
                continue;
            }
            // 查询关联的查询对象集合
            Collection rs = mmas.getQueryFace().query(batchQueryArgs.get(mmas.getTargetAttr()));
            rawSource.put(mmas.getTargetAttr(), rs);
            selectAttrMap.put(mmas.getSelectAttr(), mmas.buildRelationArgs());
        }
        /* 设置关联对象 */
        Consumer<E> composeFun = (targetObj)->{
            // 2)收集需要批量设置的属性值.为下一步批量设置准备数量
            Map<String,Object> setAttrValMap = this.collectRelateObj(targetObj, selectAttrMap, rawSource);
            // 1)批量设置组合的关联对象
            try {
                BeanHelper.setMultiAttrVal(targetObj, setAttrValMap);
            }catch (Exception e){
                String bb = "[MSMS][SerialMany]batch set attrVal fail,error:"+e.getMessage();
                logger.debug(bb);
            }
        };
        targetObjSet.stream().forEach(composeFun);
    }

    @Override
    protected String getSentinel() {
        return "SerialMany";
    }
}
